﻿'*******************************************************************************************
'* Copyright Brügmann Software GmbH, Papenburg
'* Author: Björn Kremer
'* Contact: codeplex<at>patorg.de
'* 
'* VB.CMIS is a VB.NET implementation of the Content Management Interoperability Services (CMIS) standard
'*
'* This file is part of VB.CMIS.
'* 
'* VB.CMIS is free software: you can redistribute it and/or modify
'* it under the terms of the GNU Lesser General Public License as published by
'* the Free Software Foundation, either version 3 of the License, or
'* (at your option) any later version.
'* 
'* VB.CMIS is distributed in the hope that it will be useful,
'* but WITHOUT ANY WARRANTY; without even the implied warranty of
'* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
'* GNU Lesser General Public License for more details.
'* 
'* You should have received a copy of the GNU Lesser General Public License
'* along with VB.CMIS. If not, see <http://www.gnu.org/licenses/>.
'*******************************************************************************************
Imports System.Xml

'*******************************************************************************************
'* Copyright Brügmann Software GmbH, Papenburg
'* Author: Björn Kremer
'* Contact: codeplex<at>patorg.de
'* 
'* VB.CMIS is a VB.NET implementation of the Content Management Interoperability Services (CMIS) standard
'*
'* This file is part of VB.CMIS.
'* 
'* VB.CMIS is free software: you can redistribute it and/or modify
'* it under the terms of the GNU Lesser General Public License as published by
'* the Free Software Foundation, either version 3 of the License, or
'* (at your option) any later version.
'* 
'* VB.CMIS is distributed in the hope that it will be useful,
'* but WITHOUT ANY WARRANTY; without even the implied warranty of
'* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
'* GNU Lesser General Public License for more details.
'* 
'* You should have received a copy of the GNU Lesser General Public License
'* along with VB.CMIS. If not, see <http://www.gnu.org/licenses/>.
'*******************************************************************************************
Public Class Common

   Private Shared _propertyTypes As New Dictionary(Of String, Type)
   Shared Sub New()
      _propertyTypes.Add(Common.GetXMLRootName(GetType(Properties.CmisPropertyBoolean)).ToLowerInvariant, GetType(Properties.CmisPropertyBoolean))
      _propertyTypes.Add(Common.GetXMLRootName(GetType(Properties.CmisPropertyDateTime)).ToLowerInvariant, GetType(Properties.CmisPropertyDateTime))
      _propertyTypes.Add(Common.GetXMLRootName(GetType(Properties.CmisPropertyDecimal)).ToLowerInvariant, GetType(Properties.CmisPropertyDecimal))
      _propertyTypes.Add(Common.GetXMLRootName(GetType(Properties.CmisPropertyHtml)).ToLowerInvariant, GetType(Properties.CmisPropertyHtml))
      _propertyTypes.Add(Common.GetXMLRootName(GetType(Properties.CmisPropertyId)).ToLowerInvariant, GetType(Properties.CmisPropertyId))
      _propertyTypes.Add(Common.GetXMLRootName(GetType(Properties.CmisPropertyInteger)).ToLowerInvariant, GetType(Properties.CmisPropertyInteger))
      _propertyTypes.Add(Common.GetXMLRootName(GetType(Properties.CmisPropertyString)).ToLowerInvariant, GetType(Properties.CmisPropertyString))
      _propertyTypes.Add(Common.GetXMLRootName(GetType(Properties.CmisPropertyUri)).ToLowerInvariant, GetType(Properties.CmisPropertyUri))
   End Sub

   Public Shared Function GetDataMemberValueFromEnum(val As [Enum], enumType As Type) As String
      Dim member() As Reflection.MemberInfo = enumType.GetMember(val.ToString)
      If member.Count > 0 Then
         Dim attr As Runtime.Serialization.EnumMemberAttribute() = DirectCast(member(0).GetCustomAttributes(GetType(Runtime.Serialization.EnumMemberAttribute), False), Runtime.Serialization.EnumMemberAttribute())
         Return attr(0).Value
      End If

      Return String.Empty
   End Function
   Public Shared Function GetValueByDataMemberValue(Of T)(val As String) As T
      Dim enumType As Type = GetType(T)
      val = val.ToLowerInvariant
      Dim members() As Reflection.MemberInfo = enumType.GetMembers
      For Each member As Reflection.MemberInfo In members
         If member.ReflectedType Is enumType Then
            Dim attr As Runtime.Serialization.EnumMemberAttribute() = DirectCast(member.GetCustomAttributes(GetType(Runtime.Serialization.EnumMemberAttribute), False), Runtime.Serialization.EnumMemberAttribute())
            If attr.Count > 0 Then
               Dim attrVal As String = attr(0).Value
               If attrVal.ToLowerInvariant.Equals(val) Then
                  Return DirectCast(enumType.GetField(member.Name).GetValue(Nothing), T)
               End If
            End If
         End If
      Next

   End Function
   Public Shared Function GetXMLRootName(objType As Type) As String
      Dim attr() As System.Xml.Serialization.XmlRootAttribute = DirectCast(objType.GetCustomAttributes(GetType(System.Xml.Serialization.XmlRootAttribute), False), System.Xml.Serialization.XmlRootAttribute())
      Return attr(0).ElementName
   End Function
   Public Shared Function GetXMLRootNamespace(objType As Type) As String
      Dim attr() As System.Xml.Serialization.XmlRootAttribute = DirectCast(objType.GetCustomAttributes(GetType(System.Xml.Serialization.XmlRootAttribute), False), System.Xml.Serialization.XmlRootAttribute())
      Return attr(0).Namespace
   End Function
   Public Shared Function GetItemCaseInsensitiveFromXML(doc As Xml.XmlDocument, name As String) As Xml.XmlNode
      name = name.ToLowerInvariant
      For Each child As Xml.XmlNode In doc.ChildNodes
         If GetNodeNameWithoutPrefix(child).ToLowerInvariant.Equals(name) Then
            Return child
         End If
      Next
      Return Nothing
   End Function

   Public Shared Function GetNodeNameWithoutPrefix(node As Xml.XmlNode) As String
      Dim name As String = node.Name
      If node.Prefix Is Nothing OrElse node.Prefix.Count < 1 Then
         Return name
      End If
      Return name.Substring(node.Prefix.Count + 1)
   End Function


   Public Shared Function ParseBase64(doc As Xml.XmlDocument) As Xml.XmlDocument
      For Each node As Xml.XmlNode In doc.ChildNodes
         If GetNodeNameWithoutPrefix(node).ToLowerInvariant.Equals("binary") Then
            Dim retVal As New Xml.XmlDocument()
            retVal.LoadXml(Text.Encoding.UTF8.GetString(Convert.FromBase64String(node.InnerText)))
            Return retVal
         End If
      Next
      Return doc
   End Function

   Public Shared Function GetPrefixOfNamespace(iNode As Xml.XmlNode, namespaceURI As String) As List(Of String)
      Dim retVal As New List(Of String)
      Dim node As XmlNode = Nothing
      Select Case iNode.NodeType
         Case XmlNodeType.Attribute
            node = DirectCast(iNode, XmlAttribute).OwnerElement
         Case XmlNodeType.Element
            node = iNode
         Case Else
            node = iNode.ParentNode
      End Select

      While node IsNot Nothing
         If node.NodeType = XmlNodeType.Element AndAlso DirectCast(node, XmlElement).HasAttributes Then
            For Each attr As XmlAttribute In node.Attributes
               If attr.Prefix.Equals("xmlns") AndAlso attr.Value.Equals(namespaceURI) Then
                  retVal.Add(attr.LocalName)
               ElseIf attr.Name.Equals("xmlns") AndAlso attr.Value.Equals(namespaceURI) Then
                  retVal.Add(String.Empty)
               End If
            Next
         End If
         node = node.ParentNode
      End While
      Return retVal
   End Function


   Public Shared Function ParsePropertiesNode(propertiesNode As XmlNode) As Properties.ICMISProperty()
      Dim properties As New List(Of Properties.ICMISProperty)
      For Each node As XmlNode In propertiesNode.ChildNodes
         Dim obj As Type = GetPropertyTypeByName(Common.GetNodeNameWithoutPrefix(node))
         Dim serializer As New Serialization.XmlSerializer(obj)
         Using stream As New IO.StringReader(node.OuterXml)
            properties.Add(DirectCast(serializer.Deserialize(stream), CMISObjectModel.Properties.ICMISProperty))
         End Using
      Next
      Return properties.ToArray
   End Function

   Private Shared Function GetPropertyTypeByName(propertyName As String) As Type
      propertyName = propertyName.ToLowerInvariant
      Return _propertyTypes(propertyName)
   End Function

End Class
